package se.webbzon.oschi01.worldcamera;

import java.awt.Dimension;
import java.util.Enumeration;

import javax.media.j3d.Behavior;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Locale;
import javax.media.j3d.WakeupCriterion;
import javax.media.j3d.WakeupOnElapsedTime;
import javax.vecmath.Point3d;

import se.webbzon.oschi01.worldarea.WorldAppearance3D;
import se.webbzon.oschi01.worldarea.WorldArea;
import se.webbzon.oschi01.worldarea.WorldEngine;
import se.webbzon.oschi01.worldarea.WorldEngineListener;

import com.sun.j3d.utils.universe.SimpleUniverse;

@Deprecated
public class WorldRenderer {
	
	// The minimal time between rendering
	private final long milliseconds;
	
	// The java3d universe locale of this renderer
	private final Locale locale;
	
	// The rendering behavior of this renderer
	private final BehaviorImpl behavior;
	
	// The world engine listener of this renderer
	private final WorldEngineListenerImpl listener;
	
	// Set to true when the world need to be repainted
	private boolean refresh = true;
	
	// The WorldEngine attached to this renderer
	private WorldEngine engine;
	
	// The appearance of the world attached to this renderer
	private WorldAppearance3D appearance;
	
	private final DefaultWorldView view;
	
	/*============================================================
	Constructors
	============================================================*/
	
	public WorldRenderer(long milliseconds) {
		this(milliseconds,null);
	}
	
	public WorldRenderer(long milliseconds, WorldEngine engine) {
		this.milliseconds = milliseconds;
		view = new DefaultWorldView(DefaultWorldView.TRANSPARENCY,new Dimension(640,480));
		SimpleUniverse u = new SimpleUniverse(view);
		locale = new Locale(u);
		listener = new WorldEngineListenerImpl();
		
		// Add render behavior
		BranchGroup b = new BranchGroup();
		behavior = new BehaviorImpl();
		b.addChild(behavior);
		b.compile();
		locale.addBranchGraph(b);
		
		appearance = new WorldAppearance3D(WorldAppearance3D.RENDERING_ORDER);
		locale.addBranchGraph(appearance.getJ3dBranch());
		setEngine(engine);
	}
	
	/*============================================================
	Public Methods
	============================================================*/
	
	/** Tells this renderer to refresh as soon as possible. **/
	public void refresh() {
		refresh = true;
	}
	
	/** Sets the world engine of this world renderer. **/
	public void setEngine(WorldEngine engine) {
		if (this.engine != engine) {
			if (this.engine != null)
				this.engine.removeListener(listener);
			if (engine != null)
				engine.addListener(listener);
			this.engine = engine;
		}
	}
	
	/** Returns the world engine of this world renderer. **/
	public WorldEngine getEngine() {
		return engine;
	}
	
	public DefaultWorldView getView() {
		return view;
	}
	
	/** Adds a world view to this world renderer. **/
	/*public boolean addView(WorldView view) {
		BranchGroup bg = view.getJ3dBranch();
		if (bg.getParent() == null) {
			locale.addBranchGraph(bg);
			view.setAppearance(appearance);
			return true;
		} else
			return false;
	}*/
	
	/** Removes a world view from this world renderer. **/
	public boolean removeView(WorldView view) {
		/*BranchGroup bg = view.getJ3dBranch();
		Object parent = bg.getParent();
		if (parent == null)
			return false;
		else {
			locale.removeBranchGraph(bg);
			view.setAppearance(null);
			return bg.getParent() != parent;
		}*/
		return false;
	}
	
	/*============================================================
	Private Methods
	============================================================*/
	
	/** Returns true if this renderer need to refresh. **/
	private boolean needsRefresh() {
		return refresh;
	}
	
	/** Forces the world appearance to refresh now. **/
	private void refreshNow() {
		refresh = false;
		appearance.performDraw();
	}
	
	
	/*============================================================
	Private Classes
	============================================================*/
	
	/** The behavior of this world renderer. **/
	private final class BehaviorImpl extends Behavior {
		
		private final WakeupCriterion c = new WakeupOnElapsedTime(milliseconds);
		
		public BehaviorImpl() {
			setSchedulingBounds(new BoundingSphere(new Point3d(), Double.MAX_VALUE));
		}

		@Override public void initialize() {
			wakeupOn(c);
		}

		@SuppressWarnings("rawtypes")
		@Override public void processStimulus(Enumeration arg0) {
			if (needsRefresh()) {
				refreshNow();
			}
			wakeupOn(c);
		}
		
	}
	
	/** An implementation of a world engine listener. **/
	private final class WorldEngineListenerImpl implements WorldEngineListener {

		@Override public void onSetWorldArea(WorldEngine engine, WorldArea world) {
			appearance.setWorld(world);
			refresh();
		}

		@Override public void onStepComplete(WorldEngine engine, WorldArea world) {
			refresh();
		}

		@Override
		public void onStepStartup(WorldEngine engine, WorldArea world) {
			// TODO Auto-generated method stub
			
		}
		
	}

}
